#include "WinCamera.h"
#include "dshowfun.h"
#include "dshowutil.h"
#pragma comment(lib, "strmiids")

#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
#define REGISTER_FILTERGRAPH
DWORD g_dwGraphRegister=0;

WinCamera::WinCamera(int index)
{
	g_pCapture = NULL;
	this->index = index;
}


WinCamera::~WinCamera(void)
{
}

void WinCamera::startPreview(int callback)
{
	CaptureVideo(NULL);
}

WinCamera* WinCamera::get(int index)
{
	return new WinCamera(index);
}

int WinCamera::count(){
	vector<IMoniker*>* cameras = getCameras();
	int cc = cameras->size();
	releaseMonikers(cameras);
	delete cameras;
	return cc;
}

HRESULT WinCamera::getCaptureFilter(IBaseFilter ** ppSrcFilter)
{
	HRESULT hr;
	vector<IMoniker*>* cameras = getCameras();
	IMoniker* pMoniker = cameras->at(index);
	hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppSrcFilter);
	return hr;
}

vector<IMoniker*>* WinCamera::getCameras()
{
	vector<IMoniker*>* cameras = new vector<IMoniker*>;
	IEnumMoniker *pEnum;
	HRESULT hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
	if (SUCCEEDED(hr)){
		IMoniker *pMoniker = NULL;
		while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
		{
			cameras->push_back(pMoniker);
		}
	}
	pEnum->Release();
	return cameras;
}

void WinCamera::releaseMonikers(vector<IMoniker*>* ms)
{
	for(int i=0;i<ms->size();i++){
		IMoniker *m = ms->at(i);
		m->Release();
	}
}

HRESULT WinCamera::EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
    // Create the System Device Enumerator.
    ICreateDevEnum *pDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,  
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

    if (SUCCEEDED(hr))
    {
        // Create an enumerator for the category.
        hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
        if (hr == S_FALSE)
        {
            hr = VFW_E_NOT_FOUND;  // The category is empty. Treat as an error.
        }
        pDevEnum->Release();
    }
    return hr;
}

//-------------------------

HRESULT WinCamera::CaptureVideo(IGraphBuilder* pGraphBuilder)
{
    HRESULT hr;

	// Add Capture filter to our graph.
	IBaseFilter *pSrcFilter=NULL;
    hr = getCaptureFilter(&pSrcFilter);
    hr = pGraphBuilder->AddFilter(pSrcFilter, L"Video Capture");

    // Render the preview pin on the video capture filter
    hr = g_pCapture->RenderStream (&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
                                   pSrcFilter, NULL, NULL);
    // Set video window style and position
    //hr = SetupVideoWindow();
    hr = AddGraphToRot(pGraphBuilder, &g_dwGraphRegister);
    // Start previewing video data
	IMediaControl * pMediaControl;
	hr=pGraphBuilder->QueryInterface(IID_IMediaControl,(LPVOID *) &pMediaControl);
	hr=pMediaControl->Run();
    return hr;
}
